# -*- coding: utf-8 -*-
"""
Created on Sun Oct  4 09:44:30 2020

@author: jyh
"""
import numpy as np
import itertools


def find_section(x, threshold):
    encr_section = [] #疑似加密段
    jump_point = []  #记录跳跃点的索引
    i = 0
    while i < len(x) - 1:
        if np.abs(x[i+1]-x[i]) > threshold:
            jump_point.append(i+1)
        i = i + 1
    j = 0
    true_j_point = jump_point.copy()
    fake_point = [] #用来存放需要删除的跳跃点的索引
    while j < len(jump_point)-2 and len(jump_point) >= 3:
        if jump_point[j+1] - jump_point[j] == 1 and jump_point[j+2]-jump_point[j+1]!=1 and jump_point[j+2] < len(x)-1:
            dlat1 = np.abs(x[jump_point[j+1]]-x[jump_point[j]-1])
            if dlat1 > threshold:
                fake_point.append(j+1)
            else:
                fake_point.append(j)
                fake_point.append(j+1)
            j = j + 2
        elif jump_point[j+1] - jump_point[j] == 1 and jump_point[j+2]-jump_point[j+1]==1 and jump_point[j+2] < len(x)-1:
            dlat1 = np.abs(x[jump_point[j+2]]-x[jump_point[j]])
            if dlat1 > threshold:
                fake_point.append(j)
                fake_point.append(j+1)
            else:
                fake_point.append(j+1)
                fake_point.append(j+2)
            j = j + 3
        else:
            j = j + 1
    #删除虚假跳跃点
    fake_point.reverse()#反转，从后往前删，避免index出错
    for item in fake_point:
        del true_j_point[item]
    fake_point.reverse()#再反转回来
    try:
        if true_j_point[0]==0:
            true_j_point.remove(0) #删除为0的跳跃点，第一个位置不可能是跳跃点
    except:
        raise "用户选择的阈值不当"

    #生成加密段
    if len(true_j_point)!=0:
        temp = list(range(0,true_j_point[0]))
        encr_section.append(temp)
        j = 0
        while j < len(true_j_point)-1:
            temp = list(range(true_j_point[j],true_j_point[j+1]))
            encr_section.append(temp)
            j = j + 1
        temp = list(range(true_j_point[-1],len(x)))
        encr_section.append(temp)  
        #删除平均加密概率小于0.1的加密段
        j = len(encr_section)-1
        while j >= 0:
            m = encr_section[j][0]
            n = encr_section[j][-1]
            if n>m and np.mean(x[m:n]) < 0.1:
                del encr_section[j]
            elif n==m and x[m] < 0.1:
                del encr_section[j]
            j = j-1
    else:
        print("未提取出跳跃点。")
        encr_section = []
    return encr_section

def all_combination(x):
    #函数实现x的全组合，x为列表,每一个值都是一个疑似加密字段（也是列表）
    #此处的组合是前后的连续的字段拼在一起，即假设不存在同一条报文存在两个不同位置的加密段，加密字段前后不连续
    combi = []
    if len(x)!=0:
    #    index = []
    #    for i in range(len(x)):
    #        for j in range(len(x)-i):
    #            index.append(list(range(j,j+i+1)))                           
        for i in range(1,len(x)+1):
            temp1 = list(itertools.combinations(x,i))
            for item1 in temp1:
                temp2 = []
                for item2 in item1:
                    temp2 = temp2 + item2
                combi.append(temp2)
        # if combi[0] == [0]:
        #     del combi[0]
        #删除组合中不连续的元素
        com = combi.copy() #用来存放最瓣的组合
        for it in combi:
            for j in range(len(it)-1):
                if it[j+1]-it[j] != 1:
                    com.remove(it)
                    break
        #删除从0开始加密的段
        for i in range(len(com)-1,-1,-1):
            if com[i][0] == 0 or com[i][0]==1 or len(com[i])<=5:
                com.remove(com[i])
                pass
            pass
        #保存所有可能的加密字段
        com_out = []
        for it in com:
            com_out.append([it[0],it[-1]])
        com_out = np.asfarray(com_out)
        temp = np.arange(1,len(com)+1,1)
        com_out = np.hstack((temp.reshape(len(temp),1),com_out.reshape(len(com),2)))
        np.savetxt(r'所有可能的加密字段集.txt',com_out,fmt='%0.0f',delimiter=',')
    else:
        com= []
        print(r"疑似加密字段为空。")
    return com

if __name__=="__main__":
    import rpdc_test_data_process
    import rpdc_data_reconstruct_and_prob_compute
    # data_pad,file_out,sel_data,label=rpdc_test_data_process.data_under_test(9000,9000)
    import rpdc_test_out_data_load
    f = r'zzz.dat'
    data_pad,file_out,sel_data,label = rpdc_test_out_data_load.test_data_read_file(f,0,num=5000)
    p = rpdc_data_reconstruct_and_prob_compute.data_reconstruct_and_prob_compute(data_pad, file_out)
    p_derivative = rpdc_data_reconstruct_and_prob_compute.discrete_funtion_derivative3(p)
    vari_max = 0.1  #阈值
    en_section = find_section(p,vari_max)  
    en_combination = all_combination(en_section) #这就是要显示在界面里的疑似加密段集合




